案例
先搭建一个dubbo+zookeeper的demo,然后根据demo来细说。
第一步:从dubbo官网下载dubbo-master.zip文件,从zookeeper官网下载zookeeper.tar.gz文件。
第二步:解压zookeeper.tar.gz文件,在解压\zookeeper-3.4.10\bin路径下,点击zkServer.cmd(本案例是直接在windows下运行),成功启动,发现其绑定了端口号2181。
第三步:解压dubbo-master.zip文件,然后在用eclipse导入其项目空间。发现dubbo的注入地址默认配置的是zookeeper://127.0.0.1:2181这个地址,不用修改,然后将其放到tomcat下启动。(且记先启动zookeeper在启动dubbo,不然dubbo启动连接不到zookeeper,启动失败的。)
第四步:打开http://localhost:8088/dubbo-admin-2.5.8/,然后输入账号密码,登录到dubbo管理界面。(确切地址是多少,看你的配置)。这样4步,dubbo管理平台就已经搭建好了。
第五步:在写一个消费者和生产者来同步dubbo来进行通信。先创建一个生产者。这里不详细说了,大部分都是maven工程的创建修改,直接给上代码,供大家测试调试生产者。
第六步:写一个消费者来消费生产者的服务。这里也是直接提供代码让大家来进行调试。消费者。
第七步:输入http://localhost:8089/spring-mvc/hello/dh1,发现调用已经成功,同时发现dubbo管理界面出现了一个生成者,一个消费者。
什么是zookeeper
Zookeeper是Hadoop的一个子项目,它是分布式系统中的协调系统,可提供的服务有:配置服务,名字服务,分布式同步,组服务等。
zookeeper配置文件
我们可以通过修改Zookeeper的配置文件来修改Zookeeper的启动信息。
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/opt/zookeeper-data/
clientPort=2181
tickTime:指定了ZooKeeper的基本时间单位(以毫秒为单位);
initLimit:指定了启动zookeeper时,zookeeper实例中的随从实例同步到领导实例的初始化连接时间限制,超出时间限制则连接失败(以tickTime为时间单位);
syncLimit:指定了zookeeper正常运行时,主从节点之间同步数据的时间限制,若超过这个时间限制,那么随从实例将会被丢弃;
dataDir:zookeeper存放数据的目录;
clientPort:用于连接客户端的端口。
zookeeper存储模型
Zookeeper的存储结构采用的是结构化存储,很像数据结构当中的树,也很像文件系统的目录。树是由节点所组成,Zookeeper的数据存储也同样是基于节点,这里称之为znode。但是,不同于树的节点,Znode的引用方式是路径引用,类似于文件路径:/a/b。
Znode包含4个信息。
data:Znode存储的数据信息。
ACL:记录Znode的访问权限,哪些ip那些人可以访问本节点。
stat:包含Znode的各种元数据,比如事务id,大小,时间戳等。
child:当前节点的子节点引用。
zookeeper的基本操作
create:创建节点。
delete:删除节点。
exists:判断是否存在节点。
getData:获取一个节点的数据。
setData:设置一个节点的数据。
getChildren:获取节点下所有的子节点。
其中exist,getData.getChildren 都是读操作。客户端在请求读操作时可以设置是否watch(该效果是当Znode发生改变时,如增删改时,请求watch的客户端将会接收到异步通知,也就是说当一个节点被watch后,就会在对应的哈希表里面插入被watch的Znode路径以及watch列表)。
zookeeper的一致性
Zookeeper身为分布式系统的协调服务,如果自身挂了怎么办呢?为了防止单机挂掉,ZooKeeper维护了一个集群。这个集群是一主多从结构。更新数据时,首先更新到主节点(这里的节点指的是服务器节点,不是Znode),再同步到从节点。为了保证主从节点数据一致性,zookeeper采用了ZAB协议。
ZAB协议定义了3种节点状态。
Looking:选举状态。
Following:从节点所处的状态。
Leading:Leader节点(主节点)所处的状态。
最大ZXID的概念:
最大ZXID也就是节点本地的最新事务编号,包含epoch和计数两部分。epoch是纪元的意思,相当于Raft算法选主时候的term。
从节点挂了没有任何影响。如果主节点挂了,那么集群就会进行崩溃恢复。分为3个阶段。
第一阶段,所有节点变成Looking状态。这些节点会各自向其他节点发起投票,投票信息包含自身服务器ID和最新事务ID.(ZXID)。接下来,节点会用自身的ZXID和从其他节点接受到的ZXID比较,如果别的节点比自己大,那就重新投票,投给接受到节点最大的ZXID的节点的票。
每次投完票后,服务器都会统计投票数量,判断是否存在半数以上的投票,如果存在这样的节点,那么这个节点将会成为准Leader节点,状态也会变成Leading,其他节点就会从Looking转换为Following。
第二阶段:发现阶段,用于在从节点中发现最新的ZXID和事务日志,因为可能存在Leader的ZIXD不一定是最新的,有可能意外情况,导致最新的ZXID不是最新的。
所以这个阶段,Leader集思广益,接收所有Follower发过来的epoch值,Leader从中选出最大的值,基于此值加一,生成最新的epoch分给各个Follower.各个Follower收到全新的epoch后,返回ACK给Leader,带上各自最大的ZXID和历史事务日志,Leader选出最大的ZXID,并更新自身历史日志。
第三阶段:同步阶段,将Leader刚接收到的最新历史事务日志,同步给集群所有的Follower。只有半数Follower同步成功,这个准Leader才能正式成为leader.
zookeeper的数据写入
1.客户端发出写出请求给任意的Follower。
2.Follower把写入数据的请求转发给Leader。
3.Leader采用二段提交的方式,先发送Propose广播给Follower。
4.Follower接受到Propose消息,写入日志成功后,返回ACk消息给Leader。
5.Leader接到半数以上ACK消息,返回成功给客户端,并且广播Commit请求给Follower。